﻿using System;

using System.Collections.Generic;
using System.Text;
using Silvermoon.Controls;
using System.IO;
using Silvermoon.IO;
using Silvermoon.OpenGL;
using Silvermoon.Images;
using Silvermoon.Shapes;
using Silvermoon.UI;
using Silvermoon.Utils;
using Silvermoon.Interfaces;
using System.Drawing;
using Silvermoon.Core;
using Silvermoon.Windows;
using Silvermoon.OpenGL.Native;
using Testing.Browser.IO;
using Silvermoon;

namespace Testing.Browser
{

    public class FileItem : ItemBase, ICompositeControl, IColor
    {
        #region statics

        public const int MaxOffset = 80;

        static FileItem()
        {
            CreateStateManager();
        }

        static ContextMenu contextMenu;

        protected static ContextMenu StaticContextMenu
        {
            get
            {
                if (contextMenu == null) contextMenu = CreateContextMenu();
                return contextMenu;
            }
        }
        private static ContextMenu CreateContextMenu()
        {
            ContextMenu cm = new ContextMenu
            {
                Height = 232,
                Width = 200, //  480 - 48,
                //Margin = new Margin(true, false)
            };
            cm.Items.Add(new MenuItem("Details"));
            cm.Items.Add(new MenuItem("Rename"));
            cm.Items.Add(new MenuItem("Delete"));
            return cm;
        }

        private static DataItem TextItem(string p)
        {
            throw new NotImplementedException();
        }

        private static DataItem MenuItem(string p)
        {
            throw new NotImplementedException();
        }

        #endregion
        #region fields

        public IconData iconData;

        Panel panel;
        private bool isCut;
        private PictureBox icon;
        private CheckBox selectBox;
        protected Label fileNameLabel;
        private Label dateLabel;
        private Label sizeLabel;
        private float offset;

        #endregion
        #region ctors

        protected FileItem()
            : base()
        {
            rotation.OrigX = 1f;

            TextColor = Color.White;
            IsTouchAndHoldEnabled = false;
            Initialize();
        }


        public FileItem(FolderNode node, DirectoryEntry entry)
            : this()
        {
            this.Node = node;
            InitFromEntry(entry);
            //            this.ContextMenu = FileItem.StaticContextMenu;
        }

        protected override void Dispose(bool dispose)
        {
            Cleanup();
            base.Dispose(dispose);
        }

        #endregion
        #region props

        public FolderNode Node { get; private set; }

        public FolderView FolderView
        {
            get { return ListBox as FolderView; }
        }

        public override ICommand Command
        {
            get
            {
                return FolderView != null ? FolderView.ItemCommand : null;
            }
            set
            {
            }
        }

        public DirectoryEntry Entry { get; private set; }

        public bool IsCut
        {
            get { return isCut; }
            set
            {
                if (isCut != value)
                {
                    isCut = value;
                    OnIsCutChanged();
                }
            }
        }

        protected float FolderViewOffset
        {
            get
            {
                FolderView view = ListBox as FolderView;
                return view != null ? view.ItemOffset : 0;
            }
        }

        public float Offset
        {
            get { return offset; }

            private set
            {
                if (value > 1f) value = 1f; else if (value < 0f) value = 0f;
                if (offset != value)
                {
                    offset = value;
                    OnOffsetChanged();
                }
            }
        }

        public Texture Icon
        {
            get { return icon.Image; }
            private set
            {
                icon.Image = value;
            }
        }

        public string FileName
        {
            get { return Entry.FileName; }
            set { Entry.FileName = value; }
        }

        public int FileSize
        {
            get { return Entry.FileSize; }
        }

        public DateTime Modified
        {
            get { return Entry.LastAccesTime; }
        }

        public new bool IsSelected
        {
            get { return selectBox != null && selectBox.IsChecked; }
            set
            {
                if (value != IsSelected)
                {
                    if (value == true && selectBox == null)
                    {
                        CreateCheckbox();
                    }
                    selectBox.IsChecked = value;
                }
            }
        }

        #endregion
        #region methods

        protected override void OnCommand(CommandEventArgs args)
        {
            if (args.Command == FileCommands.ToggleCheckboxCommand) selectBox.IsChecked ^= true;
            base.OnCommand(args);
        }

        private static void CreateStateManager()
        {
            VisualStateManager manager = new VisualStateManager(
                new VisualStateGroup(
                    new VisualState(VState.Unselected, 500),
                    new VisualState(VState.Selected,
                        new ColorTransition { Property = TextColorProperty, Duration = 100, To = PhoneColors.Accent })
                    ),
                new VisualStateGroup(
                    new VisualState(VState.Normal, 500),
                    new VisualState(VState.Pressed,
                    new FloatTransition { Property = YRotationProperty, To = -5f, Duration = 5 },
                //new ColorTransition { Property = Control.TextColorProperty, To = Color.White, Duration = 5 },
                    new ScaleTransition { To = new ScaleTransform(0.98f, 0.98f, 1f), Duration = 2 }
                 )
                ),
                new VisualStateGroup(
                    new VisualState("NotCut", 500),
                    new VisualState("Cut",
                        new IntTransition { Property = OpacityProperty, Duration = 500, To = 64 }
                    )
                )
            );
            VisualStateManager.RegisterClassManager(typeof(FileItem), manager);
        }

        private void OnIsCutChanged()
        {
            SetState(isCut ? "Cut" : "NotCut");
            Invalidate(InvalidationFlag.Layout);
        }

        private void CreateCheckbox()
        {
            if (selectBox == null)
            {
                selectBox = new CheckBox { Margin = new Margin(false, true) { Left = 8 }, Size = new Size(64, 64) };
                selectBox.CheckedChanged += (s, e) =>
                    {
                        IsCut = false;
                        RaiseCommand(FileCommands.ItemSelectionChangedCommand);
                    };
                VisibleControls.AddFirst(selectBox);
            }
        }

        private void Initialize()
        {
            panel = new Panel { Margin = new Margin(0) };

            fileNameLabel = new Label
            {
                Alignment = Alignment.Near,
                LineAlignment = Alignment.Near,
                Margin = new Margin(72, 4, null, 4)
            };

            dateLabel = new Label
            {
                Margin = new Margin(72, null, null, 8),
                Width = 140,
                Height = 48,
                FontScale = 0.75f,
                Opacity = 200,
                Alignment = Alignment.Near,
                LineAlignment = Alignment.Far
            };

            sizeLabel = new Label
            {
                Margin = new Margin(null, null, ScrollViewer.ScrollbarWidth, 4),
                Width = 140,
                Height = 48,
                FontScale = 0.75f,
                Opacity = 200,
                Alignment = Alignment.Far,
                LineAlignment = Alignment.Far
            };

            icon = new PictureBox
            {
                Margin = new Margin(false, true) { Left = 4 },
                Image = SysImages.Cut,
                Size = new Size(64, 64),
                Color = Color.White,
                Background = new AccentShape(PhoneColors.Blue), //  PhoneColors.Phone7Blue,
                ImageSize = new Size(48, 48)
            };
            icon.Tap += new EventHandler<TapEventArgs>(OnIconTap);


            panel.Controls.AddRange(icon, dateLabel, sizeLabel, fileNameLabel);
            VisibleControls.Add(panel);
        }

        private void OnIconTap(object sender, TapEventArgs e)
        {
            e.Handled = true;
            RaiseCommand(FileCommands.SetEditModeCommand);
        }

        private void OnOffsetChanged()
        {
            Invalidate(InvalidationFlag.Layout);
        }

        /// <summary>
        /// Occurs when to layout all shapes and child controls.
        /// </summary>
        protected override void OnLayout()
        {
            if (CheckFlag(InvalidationFlag.Size | InvalidationFlag.Layout))
            {
                fileNameLabel.Width = Width - fileNameLabel.Margin.Width - 8;
                if (offset > 0f && selectBox == null) CreateCheckbox();
                if (selectBox != null)
                {
                    int opacity = (int)(255f * offset);
                    //selectBox.Opacity = opacity;
                    selectBox.Visible = opacity > 0;

                    int leftMargin = 8 - (MaxOffset - (int)(offset * (float)MaxOffset));
                    selectBox.Margin.Left = leftMargin;
                }

                {
                    int leftMargin = (int)(offset * 80f) + 0;
                    panel.Margin.Left = leftMargin;
                }
            }
            base.OnLayout();
        }

        protected override Rectangle GetToolTipAnchor()
        {
            Size size = fileNameLabel.TextSize;
            return new Rectangle(0, 0, size.Width, size.Height);
        }

        /// <summary>
        /// Notifies an item to update it's properties. This method usually occurs when it gets visible inside a <see cref="ListBox"/> or
        /// when the listbox has changed properties that also affect items inside.
        /// In this case, the Offset property must be updated with the Offset from the FolderView that contains the item.
        /// </summary>
        public override void OnUpdateProperties()
        {
            Offset = FolderViewOffset;
        }

        ///// <summary>
        ///// Before rendering, ensure that Offset matches with FolderView.ParentOffset and update layout otherwise:
        ///// </summary>
        //protected override void OnRender(Renderer renderer)
        //{
        //    Offset = ParentOffset;
        //    base.OnRender(renderer);
        //}

        private string SizeToString()
        {
            int size = FileSize;
            if (size == 0) return string.Empty;
            return NativeMemory.FormatFileSize(size);
        }

        protected override void OnTouchDown(TouchEventArgs e)
        {
            SetState(VState.Pressed);
            base.OnTouchDown(e);
        }

        protected override void OnTouchUp(TouchEventArgs e)
        {
            SetState(VState.Normal);
            base.OnTouchUp(e);
        }

        public string FullPath { get { return Path.Combine(Node.FolderPath, FileName); } }

        protected override Shape CreateDefaultBackground()
        {
            return null;
            //return new BackgroundShape { Style = RenderStyle.Gradiented, Color = Color.Transparent };
            ////return new BackgroundShape
            ////{
            ////    Texture = ImageResource.ItemImage,
            ////    Color = System.Drawing.Color.Transparent,
            ////    Style = RenderStyle.Edged
            ////};
        }

        public void InitFromEntry(DirectoryEntry entry)
        {
            this.Entry = entry;
            dateLabel.Text = Modified.ToShortDateString();
            sizeLabel.Text = SizeToString();
            fileNameLabel.Text = entry.FileName;
            icon.Color = entry.System ? PhoneColors.Green : PhoneColors.Accent;
            LoadIcon();
        }

        public void Cleanup()
        {
            this.Entry = null;
            IconData iconData = this.iconData;
            this.iconData = null;
            if (iconData != null)
            {
                iconData.Dispose();
            }
        }

        /// <summary>
        /// Loads the icon of the file/folder and creates a TextureElement that holds the image.
        /// </summary>
        private void LoadIcon()
        {

            iconData = IconData.FromPath(this.FullPath);
            if (iconData != null)
            {
                if (!iconData.IsLoaded)
                {
                    iconData.Loaded += InvokeLoaded;
                }

                Icon = iconData.Texture;
            }
        }

        private void InvokeLoaded(object sender, EventArgs e)
        {
            Invoke(() =>
                {
                    Icon = iconData != null ? iconData.Texture : null;
                });
        }

        public override void SetAnimationState(ItemAnimationType animationType, int progress, int maxProgress, ref Rectangle bounds)
        {
            switch (animationType)
            {
                case ItemAnimationType.Insert:
                    Opacity = 255 * progress / maxProgress;
                    break;
                case ItemAnimationType.Remove:
                    Opacity = 0;
                    break;

                case ItemAnimationType.None:
                    if (!IsCut) Opacity = 255;
                    break;
            }
        }



        #endregion

    }
}
